import asyncio
import xoscar as xo
from PyCmpltrtok.common import sep


class MyActor(xo.StatelessActor):

    def estimate(self, n):
        import random
        from math import sqrt
        
        inside = 0
        for _ in range(n):
            x = random.uniform(-1., 1.)
            y = random.uniform(-1., 1.)
            if sqrt(x ** 2 + y ** 2) < 1.:
                inside += 1
        return inside
    

if '__main__' == __name__:
    
    async def main():
        
        sep('Create pool')
        dop = 7 # degree of parallelism
        address = "localhost:9999"
        # loop = asyncio.get_event_loop()
        loop = asyncio.get_running_loop()
        await loop.run_until_complete(await xo.create_actor_pool(address=address, n_process=dop))
        
        sep('Get pool config')
        pool_config = await xo.get_pool_config(address)
        print(pool_config)
        pool_addresses = pool_config.get_external_addresses()
        print(len(pool_addresses), pool_addresses)
        
        sep('Create actors')
        actors = []
        for i, address in enumerate(pool_addresses):
            actor = await xo.create_actor(MyActor, address=address, uid=str(i))
            actors.append(actor)
        print(len(actors), actors)
            
        sep('Run actors')
        N = 10 ** 7
        tasks = []
        for actor in actors:
            tasks.append(actor.estimate(N))
        
        sep('Reduce sum')
        inside = sum(await asyncio.gather(*tasks))
        pi = 4 * inside / (len(actors) * N)
        print(f'pi: {pi}')
            
    asyncio.run(main())
    